import json
import pandas as pd
import sqlalchemy
import numpy as np
from sklearn.cluster import KMeans
from flask import Flask, request, jsonify


app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False


@app.route('/getdata/<data>', methods=['GET', 'POST'])
def getdata(data):
    global a
    data = dict(json.loads(data))
    if data['current'] == 0:
        return jsonify('没有用电器')
    pre = predict(data)
    return jsonify(pre)


class ClusterPre:
    def __init__(self):
        self.engine = sqlalchemy.create_engine('mysql+pymysql://root:3751ueoxjwgixjw3913@39.98.41.126:3306/qg_mid')
        self.training_set = None
        self.his_db = None
        self.cluster = None
        self.centroid = None
        self.labels = None
        self.index_list = []

    def read_db(self):
        """
        read the data from the mysql database
        :return: None
        """
        global mysql_his_list, value_order
        for index in range(len(mysql_his_list)):
            sql = 'select * from ' + mysql_his_list[index] + ' where current !=0 and voltage >=231 and ' \
                                                             'power_factor >0 and power>0 '
            df = pd.read_sql(sql, self.engine)
            self.index_list.append(len(df['id']))
            if index == 0:
                self.training_set = np.array(df)
            else:
                tem_training_set = np.array(df)
                self.training_set = np.vstack((self.training_set, tem_training_set))
        self.his_db = self.training_set
        self.training_set = np.array(self.training_set[:, value_order], dtype=float)
        self.training_set[:, 0] *= 3000.0
        self.training_set[:, 1] -= 0
        self.training_set[:, 2] *= 100
        #  change the data in order to get a better center

    def clu_history(self):
        """
        use the history data to create a cluster center matrix
        :return: None
        """
        global n_clusters, dic, columns_list, mysql_t_list
        self.cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(self.training_set)
        self.labels = self.cluster.labels_
        self.labels = list(self.labels)
        self.his_db[:, 1] = self.labels
        self.his_db = pd.DataFrame(self.his_db, columns=columns_list)
        tem1 = 0
        for i in range(len(mysql_t_list)):
            tem_df = self.his_db.iloc[tem1:tem1+self.index_list[i], :]
            tem1 = self.index_list[i]
            tem_df.to_sql(mysql_t_list[i], self.engine, if_exists='replace', index=False)

    def save_center(self):
        """
        save the center data in order to use it next time without training
        :return: None
        """
        np.save("center.npy", self.cluster.cluster_centers_)


def predict(dict_data):
    """
    use the new data and the center matrix to cluster
    :param dict_data: the dict which is used to check which kind the center is
    :return: the kind
    """
    global values, n_clusters, dic, centers, values_list
    feature = [dict_data[v] for v in valuse_list]
    feature[0] *= 3000.0
    feature[1] -= 0
    feature[2] *= 100
    min_index = 0
    for i in range(centers.shape[0]):
        distance1 = None
        if i == 0:
            distance1 = np.sum(np.square(centers[i, :] - feature))
        else:
            distance2 = np.sum(np.square(centers[i, :] - feature))
            if distance2 < distance1:
                min_index = i
    print(dic[min_index])
    return dic[min_index]


if __name__ == '__main__':
    mysql_his_list = ['qgDevice20220730']
    mysql_t_list = ['Data20220730']
    value_order = ['current', 'voltage', 'power', 'power_factor']
    columns_list = ['id', 'name', 'current', 'voltage', 'power', 'date', 'index_num', 'power_factor', 'frequency',
                    'cumulative_power']
    dic = {0: 'phone', 1: ' computer', 2: 'oscilloscope', 3: 'oscilloscope', 4: 'router', 5: 'Hot_melt_gun', 6: 'phone',
           7: 'computer', 8: 'Hot_melt_gun', 9: 'singlechip', 10: 'computer', 11: 'Hot_melt_gun'}
    # There are some electrical appliances kinds with the number more than one
    # because one electrical appliances may have some different values with different status
    values_list = ['current', 'voltage', 'power', 'power_factor']
    values = len(values_list)
    n_clusters = len(dic)
    # centers = np.load("center.npy")
    centers = np.random.random((12, 4))
    train_flag = False
    if train_flag:
        a = ClusterPre()
        a.read_db()
        a.clu_history()
        a.save_center()
    if train_flag:
        engine_read = sqlalchemy.create_engine('mysql+pymysql://root:3751ueoxjwgixjw3913@39.98.41.126:3306/qg_mid')
        for i in range(len(mysql_t_list)):
            sql_t = 'select * from ' + mysql_t_list[i]
            read_df = pd.read_sql(sql_t, engine_read)
            print(read_df)
            for k, j in zip(read_df['name'], range(len(read_df['name']))):
                read_df.iloc[j, 1] = dic[k]
            read_df.to_sql(mysql_t_list[i], engine_read, if_exists='replace', index=False)

    app.run(host='0.0.0.0', port=8082)



